import xhr from './xhr'
import { AxiosRequestConfig, AxiosResponse, AxiosPromise } from '../types'
import { flattenHeaders } from '../helper/headers'
import { buildURL, isAbsoluteURL, combineURL } from '../helper/url'
import transform from './transform'

export default function dispatchRequest(config: AxiosRequestConfig): AxiosPromise {
  throwIfCancellationRequested(config)
  processConfig(config)
  return xhr(config).then(response => {
    processResponse(response)
    return response
  })
}

function processConfig(config: AxiosRequestConfig): void {
  const { headers = {}, data, transformRequest, transformResponse } = config
  config.url = transformURL(config)
  config.data = transform(data, headers, transformRequest)
  config.headers = flattenHeaders(config.headers, config.method!)
}

function processResponse(response: AxiosResponse): void {
  const { data, headers, config } = response
  response.data = transform(data, headers, config.transformResponse)
}

export function transformURL(config: AxiosRequestConfig): string {
  let { url, params, paramsSerializer, baseURL } = config
  if (baseURL && !isAbsoluteURL(url!)) {
    url = combineURL(baseURL, url)
  }
  return buildURL(url!, params, paramsSerializer)
}

function throwIfCancellationRequested(config: AxiosRequestConfig): void {
  if (config.cancelToken) {
    config.cancelToken.throwIfRequested()
  }
}
